'use strict'
const config = require('./config')
const Redis = require('./redis')
const Common = require('./common')
const fs = require('fs-extra')

let redisPool = {}
let cronPool = {}
let retryTimerPool = {}

const common = new Common({config, fs, cronPool})

for(let dbIndex in config.redis.dbs) {
	const {host, port, pwd} = config.redis
	const dbName = config.redis.dbs[dbIndex]
	redisPool[dbName] = new Redis(common, {host, port, pwd, db: dbIndex, name: dbName})
}
common.redis = redisPool

const ccs = {
	wx: {
		refreshAccessToken: async function(appName, config) {
			const {grantType, appId, appSecret} = config
			const {errcode, errmsg, access_token, expires_in} = await common.reqGet({
				url: 'https://api.weixin.qq.com/cgi-bin/token',
				data: {
					grant_type: grantType,
					appid: appId,
					secret: appSecret
				},
				json: true
			})
			if(errcode) {
				console.log(`refresh ${appName} access_token failed errcode:${errcode} errmsg:${errmsg}`)
				common.writeLog('error', `refresh ${appName} access_token failed errcode:${errcode} errmsg:${errmsg}`)
				this.retryRefreshAccessToken(appName, config)
				return
			}
			clearTimeout(retryTimerPool[appName])
			await redisPool.accessToken.set(appName, {
				accessToken: access_token,
				expire: expires_in,
				timestamp: common.timestamp()
			}, expires_in || 7200)
			console.log(`refresh ${appName} access_token success token:${access_token} expire:${expires_in}`)
			common.writeLog('info', `refresh ${appName} access_token success token:${access_token} expire:${expires_in}`)
		},
		retryRefreshAccessToken: function(appName, config) {
			clearTimeout(retryTimerPool[appName])
			retryTimerPool[appName] = setTimeout(() => {
				console.error(`retry refresh ${appName} access_token`)
				this.refreshAccessToken(appName, config)
			}, 60000)
		}
	},
	elyun: {
		refreshAccessToken: async function(appName, config) {
			const {grantType, clientId, clientSecret, scope} = config
			const timestamp = common.timestamp()
			const {error, error_description, body} = await common.reqPost({
				url: 'https://open-api.10ss.net/oauth/oauth',
				headers: {
					'content-type': 'application/x-www-form-urlencoded'
				},
				data: {
					grant_type: grantType,
					client_id: clientId,
					scope,
					timestamp: timestamp,
					id: common.uuid4(),
					sign: common.md5(clientId + timestamp + clientSecret)
				},
				json: true
			})
			if(error != '0') {
				console.log(`refresh ${appName} access_token failed errcode:${error} errmsg:${error_description}`)
				common.writeLog('error', `refresh ${appName} access_token failed errcode:${error} errmsg:${error_description}`)
				if(error != '41')
					this.retryRefreshAccessToken(appName, config)
				return
			}
			const {access_token, refresh_token, expires_in} = body
			clearTimeout(retryTimerPool[appName])
			await redisPool.accessToken.set(appName, {
				accessToken: access_token,
				refreshToken: refresh_token,
				expire: expires_in,
				scope: body.scope,
				timestamp: common.timestamp()
			}, expires_in || 2592000)
			console.log(`refresh ${appName} access_token success token:${access_token} expire:${expires_in}`)
			common.writeLog('info', `refresh ${appName} access_token success token:${access_token} expire:${expires_in}`)
		},
		retryRefreshAccessToken: function(appName, config) {
			clearTimeout(retryTimerPool[appName])
			retryTimerPool[appName] = setTimeout(() => {
				console.error(`retry refresh ${appName} access_token`)
				this.refreshAccessToken(appName, config)
			}, 60000)
		}
	}
}

const run = async () => {
	try {
		for(let appName in config.apps) {
			const {type, timeout} = config.apps[appName]
			await ccs[type].refreshAccessToken(appName, config.apps[appName])
			common.createJob(appName, timeout, {
				function: async (data) => {
					console.log(data)
					ccs[type].refreshAccessToken(data.appName, data.config)
				},
				params: {
					appName,
					config:  config.apps[appName]
				}
			}, {
				function: async (data) => {
					common.borderErr(`access_token refresh service ${data.appName} is stop`)
					common.writeLog('error', `access_token refresh service ${data.appName} is stop`)
				},
				params: {
					appName
				}
			}, (err) => {
				console.error(err)
				common.alertMsg('刷新AccessToken失败啦','GTCCS刷新AccessToken失败啦', err)
				common.writeLog('error', 'access_token refresh service failed', false, err)
			}, true)
		}
	}
	catch(err) {
		console.error(err)
	}
}

process.on('exit', async (code) => {
	//清除任务
	common.clearJob()
	common.borderErr(`server is stopped(${code})`)
	//服务器异常退出写入log
	common.writeLog('error', `server was terminated(code:${code})`)
})

run()